using AutoMapper;
using MediatR;
using S.O.Domain.RBAC;
using S.O.Domain.Dto.Output;
using S.O.ErrorCode;
using S.O.Interstructrue.Base;
using S.O.Api.Read.Application.Command.User;

namespace S.O.Api.Read.Application.Handler.User
{
    /// <summary>
    /// 获取用户列表处理器
    /// 负责处理用户列表查询的业务逻辑，支持分页和用户名模糊搜索，返回用户及其关联角色信息
    /// </summary>
    public class GetUserListHandler : IRequestHandler<GetUserListCommand, APIPaging<GetUserListDto>>
    {
        /// <summary>
        /// 用户仓储接口，用于用户数据的查询操作
        /// </summary>
        private readonly IBaseRepository<UserModel> userRepository;
        
        /// <summary>
        /// 角色仓储接口，用于角色数据的查询操作
        /// </summary>
        private readonly IBaseRepository<RoleModel> roleRepository;
        
        /// <summary>
        /// 用户角色关联仓储接口，用于查询用户和角色的关联关系
        /// </summary>
        private readonly IBaseRepository<UserRoleModel> userroleRepository;
        
        /// <summary>
        /// 日志记录器，用于记录操作日志和错误信息
        /// </summary>
        private readonly ILogger<GetUserListHandler> logger;
        
        /// <summary>
        /// 对象映射器，用于Model对象到DTO对象的转换
        /// </summary>
        private readonly IMapper mapper;
        
        /// <summary>
        /// 构造函数，通过依赖注入初始化所需的服务
        /// </summary>
        /// <param name="userRepository">用户仓储服务</param>
        /// <param name="roleRepository">角色仓储服务</param>
        /// <param name="userroleRepository">用户角色关联仓储服务</param>
        /// <param name="mapper">对象映射服务</param>
        /// <param name="logger">日志记录服务</param>
        public GetUserListHandler(IBaseRepository<UserModel> userRepository, 
            IBaseRepository<RoleModel> roleRepository, 
            IBaseRepository<UserRoleModel> userroleRepository, 
            IMapper mapper, 
            ILogger<GetUserListHandler> logger)
        {
            this.userRepository = userRepository;
            this.roleRepository = roleRepository;
            this.userroleRepository = userroleRepository;
            this.mapper = mapper;
            this.logger = logger;
        }
        
        /// <summary>
        /// 处理获取用户列表命令
        /// 执行用户列表查询操作，支持按用户名模糊搜索和分页，返回用户及其关联的角色信息
        /// </summary>
        /// <param name="request">获取用户列表命令对象，包含分页参数和搜索条件</param>
        /// <param name="cancellationToken">取消令牌，用于取消异步操作</param>
        /// <returns>返回包含分页用户列表数据的APIPaging对象</returns>
        public Task<APIPaging<GetUserListDto>> Handle(GetUserListCommand request, CancellationToken cancellationToken)
        {
            // 初始化分页返回结果对象
            APIPaging<GetUserListDto> res = new APIPaging<GetUserListDto>();
            
            // 获取所有未删除的用户数据
            var users = userRepository.GetALL().Where(x => x.IsDeleted == false);
            
            // 获取所有未删除的用户角色关联数据
            var userroles = userroleRepository.GetALL().Where(x => x.IsDeleted == false);
            
            // 获取所有未删除的角色数据
            var roles = roleRepository.GetALL().Where(x => x.IsDeleted == false);
            
            // 如果提供了用户名搜索条件，则进行模糊匹配过滤
            if(request.UserName != null)
            {
                users = users.Where(x => x.UserName.Contains(request.UserName));
            }
            
            // 通过LINQ连接查询获取用户和角色的关联数据
            // 连接用户表、用户角色关联表和角色表，获取完整的用户角色信息
            var userRoleData = from a in users
                       join b in userroles on a.Id equals b.UserId
                       join c in roles on b.RoleId equals c.Id
                       select new 
                       {
                           Id = a.Id,
                           UserName = a.UserName,
                           Password = a.Password,
                           RoleName = c.RoleName,
                           RoleId=c.Id,
                           IsEnable = a.IsEnable
                       };
            
            // 按用户分组，将每个用户拥有的角色名称存储到列表中
            // 这样可以处理一个用户拥有多个角色的情况
            var groupedData = userRoleData
                .GroupBy(x => new { x.Id, x.UserName, x.Password, x.IsEnable })
                .Select(g => new GetUserListDto
                {
                    Id = g.Key.Id,
                    UserName = g.Key.UserName,
                    Password = g.Key.Password,
                    RoleName = g.Select(r => r.RoleName).ToList(),
                    RoleId=g.Select(r => r.RoleId).ToList(),
                    IsEnable = g.Key.IsEnable
                }).ToList();
                
            // 执行分页处理，根据页码和页大小获取当前页的数据
            var pagedData = groupedData
                .Skip((request.Pageindex - 1) * request.PageSize)
                .Take(request.PageSize)
                .ToList();
                
            // 设置返回结果
            res.Code = APIEnums.Success;
            res.PageDatas = pagedData;
            res.TotalCount = groupedData.Count;
            res.Msg = "获取用户列表成功";
            
            // 记录操作日志
            logger.LogInformation($"获取用户列表成功，共{groupedData.Count}条记录，当前页{request.Pageindex}，页大小{request.PageSize}");
            
            return Task.FromResult(res);
        }
    }
}
